package com.softaria.promosite.server;

import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import com.softaria.windows.config.DefaultMenuConfiguration;
import com.softaria.windows.config.MenuConfiguration;
import com.softaria.windows.model.FloatPositionCalculator;
import com.softaria.windows.model.FloatSizeCalculator;
import com.softaria.windows.model.PerspectiveUrl;
import com.softaria.windows.model.ViewUrl;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class XmlMenuRepresentation {

  public static class PerspectiveDescriptor {
    private PerspectiveUrl url;
    private String label;
    private String defaultHelp;
    private String helpTitle;
    private List<ViewDescritor> views = new ArrayList<ViewDescritor>();

    public PerspectiveDescriptor(PerspectiveUrl url, String label, String helpTitle,
        String defaultHelp) {
      super();
      this.url = url;
      this.label = label;
      this.defaultHelp = defaultHelp;
      this.helpTitle = helpTitle;
    }

    public PerspectiveUrl getUrl() {
      return url;
    }

    public String getLabel() {
      return label;
    }

    public String getDefaultHelp() {
      return defaultHelp;
    }

    public String getHelpTitle() {
      return helpTitle;
    }

    public void addView(ViewDescritor view) {
      views.add(view);
    }

    public List<ViewDescritor> getViews() {
      return views;
    }
  }

  public static class ViewDescritor {
    private ViewUrl url;
    private String label;
    private String defaultHelpMessage;
    private String helpTitle;
    private FloatPositionCalculator pos;
    private FloatSizeCalculator size;

    public ViewDescritor(ViewUrl url, String label, String helpTitle, String defaultHelpMessage,
        FloatPositionCalculator posCalculator, FloatSizeCalculator sizeCalculator) {
      super();
      this.url = url;
      this.label = label;
      this.defaultHelpMessage = defaultHelpMessage;
      this.helpTitle = helpTitle;
      this.pos = posCalculator;
      this.size = sizeCalculator;

    }

    public ViewUrl getUrl() {
      return url;
    }

    public String getLabel() {
      return label;
    }

    public String getDefaultHelpMessage() {
      return defaultHelpMessage;
    }

    public String getHelpTitle() {
      return helpTitle;
    }

    public FloatPositionCalculator getPosCalculator() {
      return pos;
    }

    public FloatSizeCalculator getSizeCalculator() {
      return size;
    }

  }

  private List<PerspectiveDescriptor> perspectives = new ArrayList<PerspectiveDescriptor>();
  private PerspectiveUrl defaultPerspective;
  private static XStream xstream;

  static {
    xstream = new XStream(new DomDriver());
    xstream.alias("menu", XmlMenuRepresentation.class);
    xstream.alias("perspective", PerspectiveDescriptor.class);
    xstream.alias("view", ViewDescritor.class);
    xstream.alias("pos", FloatPositionCalculator.class);
    xstream.alias("size", FloatSizeCalculator.class);
    xstream.aliasField("x", FloatPositionCalculator.class, "leftFloat");
    xstream.aliasField("y", FloatPositionCalculator.class, "topFloat");

    xstream.aliasField("w", FloatSizeCalculator.class, "widthFloat");
    xstream.aliasField("h", FloatSizeCalculator.class, "heightFloat");
  }

  public MenuConfiguration createMenuConfiguration() {
    DefaultMenuConfiguration menuConfiguration = new DefaultMenuConfiguration();

    for (PerspectiveDescriptor pd : perspectives) {
      menuConfiguration.addPerspective(pd.getUrl(), pd.getLabel(), pd.getHelpTitle(), pd
          .getDefaultHelp());
      for (ViewDescritor vd : pd.getViews()) {

        // VERY important!!! Our XML does not contain this redundant info!
        vd.getUrl().setPerspectiveId(pd.getUrl().getPerspectiveId());

        // // Copy view label as parameter
        // String existing_param = vd.getUrl().getParameters();
        // if ((existing_param == null) || (existing_param.trim().length() ==
        // 0)) {
        // existing_param = "";
        // } else {
        // existing_param = existing_param.trim() + "&";
        // }
        // existing_param += "label=" + vd.getLabel();
        // vd.getUrl().setParameters(existing_param);

        menuConfiguration.addView(pd.getUrl(), vd.getUrl(), vd.getLabel(), vd.getHelpTitle(), vd
            .getDefaultHelpMessage(), vd.getPosCalculator(), vd.getSizeCalculator());
      }
    }
    if (defaultPerspective != null)
      menuConfiguration.setDefaultPerspective(defaultPerspective);

    return menuConfiguration;
  }

  public String createXML() {

    return xstream.toXML(this);
  }

  public static XmlMenuRepresentation createFromXml(String xml) {
    return (XmlMenuRepresentation) xstream.fromXML(xml);
  }

  public static XmlMenuRepresentation createFromXml(Reader xml) {
    return (XmlMenuRepresentation) xstream.fromXML(xml);
  }

  public static XmlMenuRepresentation createFromXml(InputStream xml) {
    return (XmlMenuRepresentation) xstream.fromXML(xml);
  }

  public void addPerspective(PerspectiveUrl url, String label, String helpTitle,
      String defaultHelpMessage) {
    perspectives.add(new PerspectiveDescriptor(url, label, helpTitle, defaultHelpMessage));
  }

  public void setDefaultPerspective(PerspectiveUrl defaultPerspective) {
    this.defaultPerspective = defaultPerspective;
  }

  public void addViewToCurrentPerspective(ViewUrl url, String label, String helpTitle,
      String defaultHelpMessage, FloatPositionCalculator posCalculator,
      FloatSizeCalculator sizeCalculator) {
    PerspectiveDescriptor pd = perspectives.get(perspectives.size() - 1);

    pd.addView(new ViewDescritor(url, label, helpTitle, defaultHelpMessage, posCalculator,
        sizeCalculator));
  }

}
